﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;

namespace Koopakiller.Numerics.Test
{
    [TestClass]
    public class LinqTest
    {
        [TestMethod, TestCategory("Ext: System.Linq:HasCount")]
        public void HasCount1()
        {
            //? check count
            List<int> list = new List<int>();
            list.Add(0);
            list.Add(1);
            list.Add(2);
            Assert.AreEqual(true, list.HasCount(0));
            Assert.AreEqual(true, list.HasCount(1));
            Assert.AreEqual(true, list.HasCount(2));
            Assert.AreEqual(true, list.HasCount(3));
            Assert.AreEqual(false, list.HasCount(4));
        }
        [TestMethod, TestCategory("Ext: System.Linq:HasCount")]
        public void HasCount2()
        {
            //? source = null
            List<int> list = null;
            try
            {
                list.HasCount(0);
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentNullException), ex.GetType());
            }
        }
        [TestMethod, TestCategory("Ext: System.Linq:HasCount")]
        public void HasCount3()
        {
            //? count < 0
            List<int> list = new List<int>();//prevent ArgumentNullException
            try
            {
                list.HasCount(-1);
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentOutOfRangeException), ex.GetType());
            }
        }

        [TestMethod, TestCategory("Ext: System.Linq:HasCount (Predicate)")]
        public void HasCountPredicate1()
        {
            //? check count
            List<int> list = new List<int>();
            list.Add(10);
            list.Add(0);
            list.Add(9);
            list.Add(11);
            Assert.AreEqual(true, list.HasCount(0, x => x < 10));
            Assert.AreEqual(true, list.HasCount(1, x => x < 10));
            Assert.AreEqual(true, list.HasCount(2, x => x < 10));
            Assert.AreEqual(false, list.HasCount(3, x => x < 10));
            Assert.AreEqual(false, list.HasCount(4, x => x < 10));
        }
        [TestMethod, TestCategory("Ext: System.Linq:HasCount (Predicate)")]
        public void HasCountPredicate2()
        {
            //? source = null
            List<int> list = null;
            try
            {
                list.HasCount(0, x => x == 0);
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentNullException), ex.GetType());
            }
        }
        [TestMethod, TestCategory("Ext: System.Linq:HasCount (Predicate)")]
        public void HasCountPredicate3()
        {
            //? count < 0
            List<int> list = new List<int>();//prevent ArgumentNullException
            try
            {
                list.HasCount(-1, x => x == 0);
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentOutOfRangeException), ex.GetType());
            }
        }
        [TestMethod, TestCategory("Ext: System.Linq:HasCount (Predicate)")]
        public void HasCountPredicate4()
        {
            //? predicate = null
            List<int> list = null;
            try
            {
                list.HasCount(0, null);
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentNullException), ex.GetType());
            }
        }

        [TestMethod, TestCategory("Ext: System.Linq:Xor")]
        public void Xor1()
        {
            int[] list = { 4, 5, 6, };
            var x = list.Xor();
            Assert.AreEqual(list[0] ^ list[1] ^ list[2], x);
        }
        [TestMethod, TestCategory("Ext: System.Linq:Xor")]
        public void Xor2()
        {
            int[] list = { -100, 0, 100 };
            var x = list.Xor();
            Assert.AreEqual(list[0] ^ list[1] ^ list[2], x);
        }
        [TestMethod, TestCategory("Ext: System.Linq:Xor")]
        public void Xor3()
        {
            int[] list = { int.MaxValue, int.MinValue, 1 };
            var x = list.Xor();
            Assert.AreEqual(list[0] ^ list[1] ^ list[2], x);
        }
        [TestMethod, TestCategory("Ext: System.Linq:Xor")]
        public void Xor4()
        {
            //? source = null
            int[] list = null;
            try
            {
                list.Xor();
                Assert.Fail("No exception");
            }
            catch (Exception ex)
            {
                Assert.AreEqual(typeof(ArgumentNullException), ex.GetType());
            }
        }

        [TestMethod, TestCategory("Ext: System.Linq:AreItemsEqual")]
        public void TestAreItemsEqual1()
        {
            string[] a1 = { "a", "b", "c", "d", "e" };
            string[] a2 = { "a", "b", "c", "d", "e" };
            string[] a3 = { "a", "b", "c", "e", "d", };
            string[] a4 = { "a", "b", "c", "d" };
            string[] a5 = { "a", "b", "d", "e" };

            bool flag = false;

            Assert.AreEqual(true, a1.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a1.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a1.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a1.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(true, a2.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a2.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a2.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a2.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(false, a3.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a3.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a3.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a3.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(false, a4.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(false, a5.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a4, (x, y) => x == y, flag));
        }
        [TestMethod, TestCategory("Ext: System.Linq:AreItemsEqual")]
        public void TestAreItemsEqual2()
        {
            string[] a1 = { "a", "b", "c", "d", "e" };
            string[] a2 = { "a", "b", "c", "d", "e" };
            string[] a3 = { "a", "b", "c", "e", "d", };
            string[] a4 = { "a", "b", "c", "d" };
            string[] a5 = { "a", "b", "d", "e" };

            bool flag = true;

            Assert.AreEqual(true, a1.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(true, a1.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a1.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a1.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(true, a2.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(true, a2.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a2.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a2.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(true, a3.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(true, a3.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a3.AreItemsEqual(a4, (x, y) => x == y, flag));
            Assert.AreEqual(false, a3.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(false, a4.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a4.AreItemsEqual(a5, (x, y) => x == y, flag));

            Assert.AreEqual(false, a5.AreItemsEqual(a1, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a2, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a3, (x, y) => x == y, flag));
            Assert.AreEqual(false, a5.AreItemsEqual(a4, (x, y) => x == y, flag));
        }
    }
}
